package com.hontech.bread.utils

import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.app.Activity
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.BitmapShader
import android.graphics.Canvas
import android.graphics.Matrix
import android.graphics.Paint
import android.graphics.RectF
import android.graphics.Shader
import android.telephony.SmsManager
import android.telephony.TelephonyManager
import android.view.MotionEvent
import android.view.View
import android.view.animation.LinearInterpolator
import androidx.core.animation.doOnEnd
import com.hontech.bread.R
import com.hontech.bread.app.AppContext
import kotlinx.coroutines.CompletableDeferred
import java.math.BigDecimal
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.Properties
import javax.mail.Authenticator
import javax.mail.Message
import javax.mail.PasswordAuthentication
import javax.mail.Session
import javax.mail.Transport
import javax.mail.internet.InternetAddress
import javax.mail.internet.MimeMessage


fun BitmapFactory.Options.scaleK(width: Int, height: Int): Int {
    val kw = outWidth.toFloat() / width
    val kh = outHeight.toFloat() / height
    return Math.min(kw, kh).toInt()
}

fun decodeBitmap(body: ByteArray, width: Int, height: Int): Bitmap {
    val option = BitmapFactory.Options()
    option.inJustDecodeBounds = true
    BitmapFactory.decodeByteArray(body, 0, body.size, option)

    val scale = option.scaleK(width, height)
    option.inJustDecodeBounds = false
    option.inSampleSize = scale

    return BitmapFactory.decodeByteArray(body, 0, body.size, option)
}

fun decodeBitmap(resId: Int, width: Int, height: Int): Bitmap {
    val option = BitmapFactory.Options()
    option.inJustDecodeBounds = true
    BitmapFactory.decodeResource(AppContext.resources, resId, option)

    val scale = option.scaleK(width, height)
    option.inJustDecodeBounds = false
    option.inSampleSize = scale

    return BitmapFactory.decodeResource(AppContext.resources, resId, option)
}

fun Bitmap.toRounded(radius: Int, imageWidth: Int, imageHeight: Int): Bitmap {
    val scaleX = imageWidth / width.toFloat()
    val scaleY = imageHeight / height.toFloat()
    val dest = Bitmap.createBitmap(imageWidth, imageHeight, Bitmap.Config.ARGB_8888)
    val paint = Paint(Paint.ANTI_ALIAS_FLAG)
    val canvas = Canvas(dest)
    val shader = BitmapShader(this, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
    paint.shader = shader.apply { setLocalMatrix(Matrix().apply { setScale(scaleX, scaleY) }) }
    val rect = RectF(0.0f, 0.0f, imageWidth.toFloat(), imageHeight.toFloat())
    canvas.drawRoundRect(rect, radius.toFloat(), radius.toFloat(), paint)
    return dest
}

fun View.setClickScaleAnimator() {
    setOnTouchListener(::onAnimTouch)
}

fun createScaleAnim(target: View, from: Float, to: Float, duration: Long): AnimatorSet {
    val set = AnimatorSet()
    val w = ObjectAnimator.ofFloat(target, "scaleX", from, to)
    val h = ObjectAnimator.ofFloat(target, "scaleY", from, to)
    set.playTogether(w, h)
    set.setTarget(target)
    set.duration = duration
    set.interpolator = LinearInterpolator()
    return set
}

fun View.playScaleAnim(min: Float = 0.95f, max: Float = 1.0f, duration: Long = 100L) {
    val anim = createScaleAnim(this, max, min, duration)
    anim.start()
    anim.doOnEnd {
        val anim2 = createScaleAnim(this, min, max, duration)
        anim2.start()
    }
}

private fun onAnimTouch(self: View, env: MotionEvent): Boolean {
    if (env.action == MotionEvent.ACTION_DOWN) {
        self.playScaleAnim()
    }
    return false
}

fun priceFormat(n: Long): String {
    val h = n / 100
    val l = n % 100
    if (l < 10) {
        return "€ ${h}.0${l}"
    }
    return "€ ${h}.${l}"
}

fun priceFormat2(n: Long): String {
    val h = n / 100
    val l = n % 100
    if (l < 10) {
        return "${h}.0${l}"
    }
    return "${h}.${l}"
}

fun parsePrice(s: String): Int {
    val n = BigDecimal(s).multiply(BigDecimal(100))
    return n.intValueExact()
}


fun currentTimestamp() = System.currentTimeMillis() / 1000

fun dateFormat(timestamp: Long): String {
    val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
    val date = Date(timestamp * 1000)
    return sdf.format(date)
}

fun dateFormat2(timestamp: Long): String {
    val sdf = SimpleDateFormat("dd/MM", Locale.getDefault())
    val date = Date(timestamp * 1000)
    return sdf.format(date)
}

@SuppressLint("MissingPermission")
fun getPhoneNumber(): String {
    val telephone = AppContext.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
    log("${stringById(R.string.t1733460848_482)}:${telephone.line1Number} - ${telephone.deviceId} - ${telephone.simSerialNumber}")
    val num = telephone.line1Number ?: stringById(R.string.t1733460848_483)
    if (num.isEmpty()) {
        return stringById(R.string.t1733460848_484)
    }
    return num
}

class SmsSendBroadcast : BroadcastReceiver() {

    companion object {
        const val SEND = "SMS_SEND"
        const val DELIVERED = "SMS_DELIVERED"
    }

    val sendPromise = CompletableDeferred<Int>()
    val deliveredPromise = CompletableDeferred<Int>()

    override fun onReceive(context: Context?, intent: Intent?) {
        log("sms broadcast ${intent?.action}")
        val action = intent?.action ?: return
        when (action) {
            SEND -> sendPromise.complete(resultCode)
            DELIVERED -> deliveredPromise.complete(resultCode)
        }
    }
}

// panini@hontechgroup.com
//${stringById(R.string.t1733460848_485)}：Panini@2024%123

private fun sendEmailImpl(email: String, sub: String, messageBody: String) {
    val username = "panini@hontechgroup.com" // ${stringById(R.string.t1733460848_486)}
    val password = "Panini@2024%123" // ${stringById(R.string.t1733460848_487)}

    val props = Properties().apply {
        put(
            "mail.smtp.host",
            "mail.hontechgroup.com"
        ) // 163 SMTP ${stringById(R.string.t1733460848_488)}
        put(
            "mail.smtp.port",
            "25"
        ) // ${stringById(R.string.t1733460848_489)}（163${stringById(R.string.t1733460848_490)}SSL${stringById(R.string.t1733460848_491)}465）
        put("mail.smtp.auth", "true") // ${stringById(R.string.t1733460848_492)}
//        put("mail.smtp.socketFactory.port", "465") // ${stringById(R.string.t1733460848_493)} SSL ${stringById(R.string.t1733460848_494)}
//        put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory") // ${stringById(R.string.t1733460848_495)} SSL
    }

    val session = Session.getInstance(props, object : Authenticator() {
        override fun getPasswordAuthentication(): PasswordAuthentication {
            return PasswordAuthentication(username, password)
        }
    })

    val message = MimeMessage(session).apply {
        setFrom(InternetAddress(username))
        setRecipients(Message.RecipientType.TO, InternetAddress.parse(email))
        subject = sub
        setText(messageBody)
    }

    Transport.send(message)
}


suspend fun sendEmail(email: String, sub: String, messageBody: String) = runIO {
    sendEmailImpl(email, sub, messageBody)
}

suspend fun sendSMS(target: String, msg: String) {

    val sendPI = PendingIntent.getBroadcast(
        AppContext, 0, Intent(SmsSendBroadcast.SEND),
        PendingIntent.FLAG_IMMUTABLE
    )
    val deliveredPI = PendingIntent.getBroadcast(
        AppContext, 0, Intent(SmsSendBroadcast.DELIVERED),
        PendingIntent.FLAG_IMMUTABLE
    )

    val receiver = SmsSendBroadcast()
    val filter = IntentFilter()
    filter.addAction(SmsSendBroadcast.SEND)
    filter.addAction(SmsSendBroadcast.DELIVERED)
    AppContext.registerReceiver(receiver, filter)

    try {
        SmsManager.getDefault()
            .sendTextMessage(target, null, msg, sendPI, deliveredPI)
        val sendCode =
            receiver.sendPromise.await(10 * 1000, "${stringById(R.string.t1733460848_496)}")
        if (sendCode != Activity.RESULT_OK) {
            throw IllegalStateException("${stringById(R.string.t1733460848_497)}:${sendCode}")
        }
        val dc =
            receiver.deliveredPromise.await(10 * 1000, "${stringById(R.string.t1733460848_498)}")
        if (dc != Activity.RESULT_OK) {
            throw IllegalStateException("${stringById(R.string.t1733460848_499)}:${dc}")
        }
    } finally {
        AppContext.unregisterReceiver(receiver)
    }

}


























